"""
Case Type   : 资源池化故障模式库
Case Name   : pg_xlog文件丢失-pg_xlog日志文件丢失
Create At   : 2025/05
Owner       : haomeng
Description :
    1、修改对应参数，重启使其生效
    2、查看集群状态
    3、运行tpcc业务
    4、查看当前xlog位置及其对应文件名
    5、删除当前位置xlog文件
    6、查看业务状态
    7、重启集群，查看集群状态
    8、恢复xlog文件
    9、恢复集群状态
Expect      :
    1、修改参数成功，重启生效
    2、集群状态正常
    3、运行业务成功
    4、查看xlog位置及其对应文件名成功
    5、删除xlog文件成功
    6、业务运行异常
    7、重启集群，集群状态正常
    8、恢复xlog文件成功
    9、集群状态正常
History     :
"""

import os
import time
import unittest

from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH
from testcase.utils.ComThread import ComThread
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import Node
from yat.test import macro

class SSFauleMode(unittest.TestCase):

    def setUp(self):
        self.log = Logger()
        self.log.info(f'----{os.path.basename(__file__)} start----')
        self.user_node = [Node(node='PrimaryRoot'), Node(node='PrimaryDbUser')]
        self.pri_sh = CommonSH('PrimaryDbUser')
        self.com = Common()
        self.constant = Constant()
        self.param_list = ['checkpoint_segments', 'checkpoint_timeout']
        self.value_list = ['256', '30min']

        self.default_value = []
        for param in self.param_list:
            value = self.com.show_param(f'{param}')
            self.default_value.append(value)
        self.log.info(self.default_value)

        self.vg_conf = os.path.join(macro.DSS_INSTANCE_PATH, 'cfg', 'dss_vg_conf.ini')
        self.vg_name = self.user_node[1].sh(
            f"cat {self.vg_conf} | awk 'NR==2' | awk -F ':' '{{{{print $1}}}}'").result()
        self.log.info(self.vg_name)

    def test_ss_faule(self):
        text = '-----step1:修改对应参数，重启使其生效;  expect:修改参数成功，重启成功-----'
        self.log.info(text)

        for param in self.param_list:
            set_param = self.pri_sh.execute_gsguc('set',
                                              self.constant.GSGUC_SUCCESS_MSG,
                                              f'{param} = {self.value_list[self.param_list.index(param)]}')
            self.log.info(set_param)
            self.assertTrue(set_param, '参数设置失败')

        self.log.info('---重启集群使参数生效---')
        restart = self.pri_sh.restart_db_cluster()
        self.log.info(restart)
        self.assertTrue(restart, '集群重启失败')

        self.log.info('---查看参数值修改是否成功---')
        for param in self.param_list:
            value = self.com.show_param(f'{param};')
            self.assertEqual(value,
                             self.value_list[self.param_list.index(param)], '参数未修改成功')

        text = '-----step2:查看集群状态  expect:集群状态正常-----'
        self.log.info(text)

        status = self.pri_sh.exec_cm_ctl('query', '-Cv')
        self.log.info(status)
        self.assertIn('Normal', status, '集群状态异常')

        text = '-----step3:查看当前xlog位置及其文件名  expect:获取成功-----'
        self.log.info(text)

        xlog = self.pri_sh.execut_db_sql(f'select * from pg_current_xlog_location();')
        xlog_location = xlog.splitlines()[-2].strip()
        self.log.info(xlog_location)

        filename = self.pri_sh.execut_db_sql(f"select * from pg_xlogfile_name('{xlog_location}');")
        self.xlog_filename = filename.splitlines()[-2].strip()
        self.log.info(self.xlog_filename)

        self.new_xlog_name = self.xlog_filename + '_new_xlog'
        self.log.info(self.new_xlog_name)

        text = '-----step4:执行tpcc读写业务  expect:业务执行成功-----'
        self.log.info(text)

        tpcc_cmd = f'./runBenchmark.sh {macro.PROPS_FILENAME}'
        self.log.info(tpcc_cmd)

        tpcc_execute = ComThread(self.com.start_tpcc, args=(self.user_node[0],
                                                            f'{macro.TPCC_PATH}',
                                                            tpcc_cmd))
        tpcc_execute.setDaemon(True)
        tpcc_execute.start()

        text = '-----step5:删除当前位置xlog文件  expect:删除成功-----'
        self.log.info(text)

        rename = f'source {macro.DB_ENV_PATH};' \
                 f'dsscmd cp -s +{self.vg_name}/pg_xlog/{self.xlog_filename} -d +{self.vg_name}/pg_xlog/{self.new_xlog_name};' \
                 f'dsscmd rm -p +{self.vg_name}/pg_xlog/{self.xlog_filename};'
        self.log.info(rename)

        rename_execute = ComThread(self.com.get_sh_result, args=(self.user_node[1], rename))
        rename_execute.setDaemon(True)
        rename_execute.start()

        text = '-----step6:查看业务运行情况  expect:业务运行异常终止-----'
        self.log.info(text)

        tpcc_execute.join()
        ret2 = tpcc_execute.get_result()
        self.log.info(ret2)
        self.assertIn('Session End', ret2, 'tpcc执行失败')

        rename_execute.join()
        ret1 = rename_execute.get_result()
        self.log.info(ret1)
        self.assertIn('Succeed to remove device', ret1, 'xlog文件删除失败')

        text = '-----step7:重启集群，查看集群状态  expect:集群状态正常-----'
        self.log.info(text)

        restart = self.pri_sh.exec_cm_ctl('stop;','cm_ctl start')
        self.log.info(restart)
        self.assertIn(self.constant.cm_start_success_msg, restart, '集群重启失败')

        status = self.pri_sh.exec_cm_ctl('query', '-Cv')
        self.log.info(status)
        self.assertIn('cluster_state   : Normal', status, '集群状态异常')

    def tearDown(self):
        text = '-----step8:恢复xlog文件名称  expect:恢复成功-----'
        self.log.info(text)

        recovery = f'source {macro.DB_ENV_PATH};' \
                   f'dsscmd rename -o +{self.vg_name}/pg_xlog/{self.new_xlog_name} -n +{self.vg_name}/pg_xlog/{self.xlog_filename};'
        self.log.info(recovery)
        recovery_res = self.user_node[1].sh(recovery).result()
        self.log.info(recovery_res)

        text = '-----step9：恢复集群初始状态，查看集群状态  expect:恢复集群状态成功-----'
        self.log.info(text)

        restart = self.pri_sh.exec_cm_ctl('stop;','cm_ctl start')
        self.log.info(restart)

        time.sleep(30)
        status = self.pri_sh.exec_cm_ctl('query', '-Cv')
        self.log.info(status)

        if 'P Primary' not in status:
            switch = self.pri_sh.exec_cm_ctl('switchover', '-a')
            self.log.info(switch)
            self.assertIn(self.constant.cm_switchover_success_msg, switch, '切换主节点失败')
        self.assertIn('Succeed to rename file', recovery_res, '恢复xlog文件失败')
        self.log.info(f'----{os.path.basename(__file__)} end----')
